﻿using System;
using System.Collections.Generic;
using System.Text;

using System.ComponentModel;
using System.Data;

using XCode;
using XCode.Attributes;
using XCode.Entity;
using XCode.DataAccessLayer;
using System.Security.Cryptography;
using System.Web;

namespace XCMSData
{
    /// <summary>
    /// 用户
    /// </summary>
    public partial class User : Entity
    {
        #region 事件
        #region 初始化
        /// <summary>
        /// 初始化 用户 对象时触发
        /// </summary>
        /// <param name="k">初始化位置，1是空参数，2是全参数，3是标识参数</param>
        private void OnInit(int k)
        {
        }
        #endregion

        #region 插入
        /// <summary>
        /// 插入前
        /// </summary>
        /// <returns>是否允许插入</returns>
        private static Boolean OnInserting()
        {
            return true;
        }

        /// <summary>
        /// 插入后
        /// </summary>
        /// <param name="retval">影响的行数</param>
        /// <returns>影响的行数</returns>
        private static Int32 OnInserted(Int32 retval)
        {
            hasUpdated = false;
            return retval;
        }

        /// <summary>
        /// 已重载。把该对象插入到数据库。
        /// </summary>
        /// <returns>影响的行数</returns>
        public override Int32 Insert()
        {
            if (!OnInserting()) return -1;
            PassWord = Hash(PassWord);
            return OnInserted(base.Insert());
        }
        #endregion

        #region 更新
        /// <summary>
        /// 更新前
        /// </summary>
        /// <returns>是否允许更新</returns>
        private static Boolean OnUpdating()
        {
            return true;
        }

        /// <summary>
        /// 更新后
        /// </summary>
        /// <param name="retval">影响的行数</param>
        /// <returns>影响的行数</returns>
        private static Int32 OnUpdated(Int32 retval)
        {
            hasUpdated = false;
            return retval;
        }

        /// <summary>
        /// 已重载。更新数据库。
        /// </summary>
        /// <returns>影响的行数</returns>
        public override Int32 Update()
        {
            if (!OnUpdating()) return -1;
            User u = User.FindByKey(ID);
            if (String.IsNullOrEmpty(PassWord))
                PassWord = u.PassWord;
            else if (u.PassWord != PassWord)
                PassWord = Hash(PassWord);
            return OnUpdated(base.Update());
        }
        #endregion

        #region 删除
        /// <summary>
        /// 删除前
        /// </summary>
        /// <returns>是否允许删除</returns>
        private static Boolean OnDeleting()
        {
            return true;
        }

        /// <summary>
        /// 删除后
        /// </summary>
        /// <param name="retval">影响的行数</param>
        /// <returns>影响的行数</returns>
        private static Int32 OnDeleted(Int32 retval)
        {
            hasUpdated = false;
            return retval;
        }

        /// <summary>
        /// 已重载。从数据库中删除该对象
        /// </summary>
        /// <returns>影响的行数</returns>
        public override Int32 Delete()
        {
            if (!OnDeleting()) return -1;
            return OnDeleted(base.Delete());
        }
        #endregion
        #endregion

        #region 查找
        /// <summary>
        /// 查找
        /// </summary>
        /// <param name="condition">条件</param>
        /// <param name="__order">排序</param>
        /// <param name="startRowIndex">开始行</param>
        /// <param name="maximumRows">最大行数</param>
        /// <returns></returns>
        [DataObjectMethod(DataObjectMethodType.Select, false)]
        public static IList<User> Search(string condition, String __order, int startRowIndex, int maximumRows)
        {
            //return User.SelectAll(User._.UserName + " like '%" + condition + "%'", null, null, 0, 20);
            //return Select<User>("select * from X_User where X_UserName like '%" + condition + "%'");
            //上面的方法是不推荐使用的
            String str = SearchWhere(condition);
            return SelectAll(str, __order, null, startRowIndex, maximumRows);
        }

        /// <summary>
        /// 每一个查找方法，都必须对应一个拥有一模一样的参数（名字顺序类型都一致）的Count方法，
        /// 这样页面控件才能使用实体类内部的分页机制。
        /// 因为这两个方法所产生的where条件是一样的，只是最后调用的方法有所不同而已，
        /// 所以可以新增第三个函数用处生成where字句。
        /// </summary>
        /// <param name="condition">条件</param>
        /// <param name="__order">排序</param>
        /// <param name="startRowIndex">开始行</param>
        /// <param name="maximumRows">最大行数</param>
        /// <returns></returns>
        public static Int32 SearchCount(string condition, String __order, int startRowIndex, int maximumRows)
        {
            String str = SearchWhere(condition);
            return SelectCount(str, __order, null, startRowIndex, maximumRows);
        }

        private static String SearchWhere(string condition)
        {
            if (String.IsNullOrEmpty(condition) || String.IsNullOrEmpty(condition.Trim())) return null;

            StringBuilder sb = new StringBuilder();
            sb.Append("1<>1");

            //如果是数字，试试ID
            int k = 0;
            if (int.TryParse(condition, out k)) sb.AppendFormat(" Or {0}={1}", User._.ID, condition);

            //要把单引号替换成为两个单引号，防止SQL注入
            sb.AppendFormat(" Or {0} like '%{1}%'", _.UserName, condition.Replace("'", "''"));
            sb.AppendFormat(" Or {0} like '%{1}%'", _.LastLoginIP, condition.Replace("'", "''"));
            return sb.ToString();
        }
        #endregion

        #region 登录
        public static User Login(String UserName, String PassWord, bool EquallyValidateCode)
        {
            // 检查用户名
            if (String.IsNullOrEmpty(UserName))
            {
                return null;
            }
            // 查找用户
            IList<User> users = SelectAll(_.UserName, UserName);
            // 是否找到
            if (users == null || users.Count < 1)
            {
                throw new Exception("用户[" + UserName + "]不存在");
            }
            // 是否有同名用户存在
            if (users.Count > 1)
            {
                throw new Exception("系统有多个名为[" + UserName + "]的用户，请与管理员联系");
            }
            //是审核通过
            //if (users[0].IsApproved == (int)ApproveValue.UnApproveuser) throw new Exception("用户[" + UserName + "]已经还未被审核通过");
            // 是否锁定
            //if (users[0].IsLockedOut == (int)LockValue.UserLock) throw new Exception("用户[" + UserName + "]已经被锁定");
            // 比较密码
            if (!(String.IsNullOrEmpty(users[0].PassWord) && String.IsNullOrEmpty(PassWord)))
            {
                if (users[0].PassWord != Hash(PassWord)) throw new Exception("密码不正确");
            }
            return users[0];
        }
        public static void LoginUpdate(User obj, string UserHostAddress)
        {
            if (obj == null)
            {
                return;
            }
            obj.LastLoginTime = DateTime.Now;
            obj.Logins = obj.Logins + 1;
            obj.LastLoginIP = UserHostAddress;
            User.Update(obj);
        }

        /// <summary>
        /// 散列算法
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        public static String Hash(String text)
        {
            if (String.IsNullOrEmpty(text)) return null;
            MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
            Byte[] bts = Encoding.UTF8.GetBytes(text);
            bts = md5.ComputeHash(bts);
            return BitConverter.ToString(bts).Replace("-", "");
        }
        #endregion

        #region 扩展属性
        /// <summary>
        /// 当前用户
        /// </summary>
        public static User Current
        {
            get
            {
                return HttpContext.Current.Session["XCMS_User"] as User;
            }
            set
            {
                HttpContext.Current.Session.Add("XCMS_User", value);
            }
        }

        /// <summary>
        /// 是否已经登录s
        /// </summary>
        public static Boolean IsLogined
        {
            get
            {
                return Current != null;
            }
        }
        #endregion
    }
}